package com.hello.sky.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hello.sky.constant.MessageConstant;
import com.hello.sky.constant.StatusConstant;
import com.hello.sky.exception.SkyException;
import com.hello.sky.mapper.CategoryMapper;
import com.hello.sky.mapper.SetmealDishMapper;
import com.hello.sky.mapper.SetmealMapper;
import com.hello.sky.model.dto.SetmealDTO;
import com.hello.sky.model.dto.SetmealPageQueryDTO;
import com.hello.sky.model.entity.Category;
import com.hello.sky.model.entity.Setmeal;
import com.hello.sky.model.entity.SetmealDish;
import com.hello.sky.model.vo.SetmealVO;
import com.hello.sky.result.PageResult;
import com.hello.sky.service.SetmealDishService;
import com.hello.sky.service.SetmealService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 套餐 服务实现类
 * </p>
 *
 * @author D
 */
@Slf4j
@Service
public class SetmealServiceImpl extends ServiceImpl<SetmealMapper, Setmeal> implements SetmealService {

    @Autowired
    private SetmealDishMapper setmealDishMapper;
    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private SetmealDishService setmealDishService;

    @CacheEvict(cacheNames = "setmealCache", key = "#a0.categoryId")
    @Transactional
    @Override
    public void addSetmeal(SetmealDTO dto) {
        //插入套餐表
        Setmeal setmeal = new Setmeal();
        BeanUtils.copyProperties(dto, setmeal);
        setmeal.setStatus(StatusConstant.DISABLE);
        baseMapper.addSetMeal(setmeal);
        Long id = setmeal.getId();
        //插入套餐菜品表
        List<SetmealDish> setmealDishList = dto.getSetmealDishes();
        setmealDishList.forEach(dish -> dish.setSetmealId(id));
        setmealDishMapper.addBatch(setmealDishList);
    }

    @Override
    public PageResult getPage(SetmealPageQueryDTO dto) {
        //连表查询，封装在sql中
        List<SetmealVO> page = baseMapper.getPage(dto);
        //为查询分类名称
        if (page.size() == 0) return new PageResult(0, null);
        List<Long> ids = page.stream().map(SetmealVO::getCategoryId).collect(Collectors.toList());
        List<Category> categories = categoryMapper.selectList(new LambdaUpdateWrapper<Category>().in(Category::getId, ids));
        Map<Long, Category> map = categories.stream().collect(Collectors.toMap(Category::getId, category -> category));
        page.forEach(vo -> {
            vo.setCategoryName(String.valueOf(map.get(vo.getCategoryId()).getName()));
        });
        return new PageResult(page.size(), page);

    }

    @Override
    public SetmealVO getSetmealByIdResVo(Long id) {
        return baseMapper.getSetmealByIdResVo(id);
    }

    @CacheEvict(cacheNames = "setmealCache", key = "#a0.categoryId")
    @Transactional
    @Override
    public void updateSetmealWithDishAndCategory(SetmealDTO dto) {
        //更新setmeal
        Setmeal setmeal = new Setmeal();
        BeanUtils.copyProperties(dto, setmeal);
        baseMapper.updateSetmeal(setmeal);

        //更新setmealDish
        List<SetmealDish> dishList = dto.getSetmealDishes();
        setmealDishService.updateBySetmealId(setmeal.getId(), dishList);
    }

    @CacheEvict(cacheNames = "setmealCache", allEntries = true)
    @Override
    public void updateSetmealStatus(Long id, Integer status) {
        //套餐内如果有停售菜品，则套餐无法上架

        //查询该套餐包含的所有菜品有没有停售的
        Integer count = setmealDishMapper.getDisableDishBySetmealId(id, StatusConstant.DISABLE);

        //改套餐有未启用的菜品，报错无法上架
        if (count != null && count > 0) throw SkyException.cast(MessageConstant.SETMEAL_ENABLE_FAILED);

        Setmeal setmeal = new Setmeal();
        setmeal.setId(id);
        setmeal.setStatus(status);
        baseMapper.updateSetmealStatus(setmeal);
    }

    @CacheEvict(cacheNames = "setmealCache", allEntries = true)
    @Transactional
    @Override
    public void delSetmeaByIds(List<Long> ids) {
        List<Setmeal> setmealList = baseMapper.selectByIds(ids);
        boolean b = setmealList.stream().anyMatch(setmeal -> setmeal.getStatus() == StatusConstant.ENABLE);
        //有在售的套餐，直接返回
        if (b) throw SkyException.cast(MessageConstant.SETMEAL_ON_SALE);
        baseMapper.delBatchByIds(ids.toArray(new Long[0]));
        setmealDishMapper.delBySetmealId(ids.toArray(new Long[0]));
    }


    @Cacheable(cacheNames = "setmealCache", key = "#a0")
    @Override
    public List<SetmealVO> getSetmealByCategoryIdResVo(Integer id) {
        return baseMapper.getSetmealByCategoryIdResVo(id, StatusConstant.ENABLE);
    }

    @Override
    public List<SetmealDish> getSetmealDishBySetmealId(Long setmealId) {
        return baseMapper.getSetmealDishBySetmealId(setmealId);
    }
}
